package me.caofeng.service;

import com.alipay.demo.trade.model.ExtendParams;
import com.alipay.demo.trade.model.GoodsDetail;
import com.alipay.demo.trade.model.builder.AlipayTradePrecreateRequestBuilder;
import me.caofeng.dao.OrderMapper;
import me.caofeng.enums.OrderStatus;
import me.caofeng.enums.ResponseCode;
import me.caofeng.pojo.AlipayInfo;
import me.caofeng.pojo.Order;
import me.caofeng.pojo.Response;
import me.caofeng.service.api.IAlipayService;
import me.caofeng.service.api.IFileService;
import me.caofeng.service.api.IPreparePayService;
import me.caofeng.util.JsonUtil;
import me.caofeng.util.PriceUtil;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

/**
 * Copyright © 2017曹峰. All rights reserved.
 *
 * @Prject: mall
 * @Package: me.caofeng.service
 * @Description:
 * @Author: 曹峰 blog.caofeng.me
 * @Date: 2017-06-28 19:09
 * @Version: V1.0
 */
@Service
@Transactional
public class PreparePayService implements IPreparePayService {
    private static Logger LOGGER = LogManager.getLogger(PreparePayService.class);

    @Autowired
    private IAlipayService alipayService;

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private IFileService fileService;

    @Override
    public Response<String> preparePay(String orderId, String userId, int payMethod) {
        // 验证订单是否存在
        Order order = orderMapper.getOrder(userId, orderId);

        if (null == order) {
            LOGGER.debug("订单不存在");
            return Response.response(ResponseCode.ILLEGAL_ARGUMENT, "订单不存在", null);
        }

        Response<String> response = null;
        order.setItems(orderMapper.getOrderItems(userId,orderId));
        //发起支付
        switch (payMethod) {
            case 1:
                if (alipayService.getPayStatus(orderId).isSuccess()) {
                    return Response.response(ResponseCode.SUCCESS, "订单已支付", null);
                }
                LOGGER.info(JsonUtil.toJSon(order));
                response = prepareAlipay(order);
                break;
            case 2:
                return prepareWechatpay();
        }

        if (!response.isSuccess()) {
            return response;
        }

        //生成二维码
        response = fileService.saveQrCode(response.getData(), orderId);

        //保存支付信息
        savePayInfo(orderId, userId, payMethod,order.getPayPrice());

        return response;

    }

    @Override
    public Response getPayStatus(String orderId, String userId, int payMethod) {
        // 判断支付订单是否存在且是该用户的支付订单
        Integer id = orderMapper.isOrderExists(userId, orderId);

        if (null == id || id <= 0) {
            return Response.response(ResponseCode.ILLEGAL_ARGUMENT, "订单存不存在", null);
        }

        switch (payMethod) {
            case 1:
                return alipayService.getPayStatus(orderId);
            default:
                return Response.response(ResponseCode.ERROR, "获取支付状态失败", null);
        }
    }

    private Response<String> prepareWechatpay() {
        return Response.response(ResponseCode.SUCCESS, "微信支付成功", null);
    }

    private Response<String> prepareAlipay(Order order) {

        //todo 组装支付宝支付信息
        // (必填) 商户网站订单系统中唯一订单号，64个字符以内，只能包含字母、数字、下划线，
        // 需保证商户系统端不能重复，建议通过数据库sequence生成，
        String outTradeNo = order.getOrderId();

        // (必填) 订单标题，粗略描述用户的支付目的。如“xxx品牌xxx门店当面付扫码消费”
        String subject = "有空商城付扫码消费";

        // (必填) 订单总金额，单位为元，不能超过1亿元
        // 如果同时传入了【打折金额】,【不可打折金额】,【订单总金额】三者,则必须满足如下条件:【订单总金额】=【打折金额】+【不可打折金额】
        String totalAmount = PriceUtil.intToString(order.getPayPrice());

        // (可选) 订单不可打折金额，可以配合商家平台配置折扣活动，如果酒水不参与打折，则将对应金额填写至此字段
        // 如果该值未传入,但传入了【订单总金额】,【打折金额】,则该值默认为【订单总金额】-【打折金额】
        String undiscountableAmount = "0";

        // 卖家支付宝账号ID，用于支持一个签约账号下支持打款到不同的收款账号，(打款到sellerId对应的支付宝账号)
        // 如果该字段为空，则默认为与支付宝签约的商户的PID，也就是appid对应的PID
        String sellerId = "";

        // 订单描述，可以对交易或商品进行一个详细地描述，比如填写"购买商品2件共15.00元"
        String body = "购买商品" + order.getItems().size() + "件共" +totalAmount + "元";

        // 商户操作员编号，添加此参数可以为商户操作员做销售统计
        String operatorId = "ykkj";

        // (必填) 商户门店编号，通过门店号和商家后台可以配置精准到门店的折扣信息，详询支付宝技术支持
        String storeId = "ykkj";

        // 业务扩展参数，目前可添加由支付宝分配的系统商编号(通过setSysServiceProviderId方法)，详情请咨询支付宝技术支持
        ExtendParams extendParams = new ExtendParams();
        extendParams.setSysServiceProviderId("2088100200300400500");

        // 支付超时，定义为120分钟
        String timeoutExpress = "120m";

        // 商品明细列表，需填写购买商品详细信息，
        List<GoodsDetail> goodsDetailList = new ArrayList<GoodsDetail>();

        // 创建一个商品信息，参数含义分别为商品id（使用国标）、名称、单价（单位为分）、数量，如果需要添加商品类别，详见GoodsDetail
        // 创建好一个商品后添加至商品明细列表
        order.getItems().forEach(orderItem ->
                goodsDetailList.add(GoodsDetail.newInstance(
                        String.valueOf(orderItem.getProductId()), orderItem.getProductName(), orderItem.getTotalPrice(), orderItem.getQuantity()))
        );

        // 创建扫码支付请求builder，设置请求参数
        AlipayTradePrecreateRequestBuilder builder = new AlipayTradePrecreateRequestBuilder()
                .setSubject(subject).setTotalAmount(totalAmount).setOutTradeNo(outTradeNo)
                .setUndiscountableAmount(undiscountableAmount).setSellerId(sellerId).setBody(body)
                .setOperatorId(operatorId).setStoreId(storeId).setExtendParams(extendParams)
                .setTimeoutExpress(timeoutExpress)
                .setNotifyUrl("http://ykkeji.s1.natapp.cc/mall/pay/callback/alipay")//支付宝服务器主动通知商户服务器里指定的页面http路径,根据需要设置
                .setGoodsDetailList(goodsDetailList);
        return alipayService.pay(builder);
    }

    private boolean savePayInfo(String orderId, String userId, int platform,int price) {
        int row = 0;
        switch (platform) {
            case 1:
                AlipayInfo alipayInfo = new AlipayInfo();
                alipayInfo.setUserId(userId);
                alipayInfo.setOrderId(orderId);
                alipayInfo.setOrderStatus(OrderStatus.UNPAID);
                alipayInfo.setTotalAmount(price);
                row = orderMapper.addAlipayInfo(alipayInfo);
                break;
        }

        return row == 1;
    }

}
